# -*- coding:utf-8 -*-

## =====================================================================
## Copyright (C) 2007-2011  Jean-Philippe GOLAY
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## =====================================================================


from Tkinter import *
import Pmw
from tkMessageBox import *

from Persistance import *
from iCalendar import CalendarGUI
from iTime import TimePopupGUI
from iNotes import NotesGUI
from iStaff import StaffListGUI
from iPlace import PlaceListGUI
from iItem import ItemListGUI
from iBill import BillListGUI


class StockGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.title(u"Stock")
		self.balloon=balloon
		self.imgSave=PhotoImage(file="img/save_icon.gif")
		self.imgDelete=PhotoImage(file="img/delete_icon.gif")
		self.imgCalendar=PhotoImage(file="img/calendar.gif")
		self.imgTime=PhotoImage(file="img/time_icon.gif")
		self.imgSearch=PhotoImage(file="img/search_icon.gif")
		self.imgNotes=PhotoImage(file="img/edit.gif")
		self.hoursListCB = Glob.HOURS_LIST
		self.minutesListCB = Glob.MINUTES_LIST
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Stock-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Stock-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre...")
		self.log.info("\tStockGUI\tStart")
		self.makeStock()

	# DEBUT de la gestion du module Stock ------------------------------------------------------------------------------------------------------------------
	def clearFieldStock(self):
		# Mise a zéro des champs
		self.stockValues[0].set("")
		self.stockValues[1].set("")
		self.stockValues[2].set(u"EC")
		self.stockValues[3].set("")
		self.stockValues[4].set("")
		self.stockValues[5].set("")
		self.stockValues[6].set("")
		self.stockValues[7].set("")
		self.stockValues[8].set("")
		self.stockValues[9].set("")
		self.stockValues[10].set("")
		self.stockStatusCB.selectitem(1)
		self.hourStockDeliveryDateCB.selectitem(0)
		self.minStockDeliveryDateCB.selectitem(0)
		self.stockHourDeliveryDate=StringVar()
		self.stockMinuteDeliveryDate=StringVar()
		self.listObject=[Place,Item,Bill,Staff]

	def selectStock(self, event):
		if self.listStock.get(0)!="":
			result = Stock.select(Stock.q.id==self.idListStock[int(self.listStock.curselection()[0])])
			for row in result:
				self.selectedStock = row
			self.listObject[0]=self.selectedStock.place
			self.listObject[1]=self.selectedStock.item
			self.listObject[2]=self.selectedStock.bill
			self.listObject[3]=self.selectedStock.checkBy
			self.stockValues[0].set(self.listObject[0].company)
			self.stockValues[1].set(self.listObject[1].designation)
			if self.selectedStock.bill != None:self.stockValues[3].set(self.listObject[2].reference)
			self.stockValues[9].set(self.listObject[3].fname+" - "+self.listObject[3].lname)
			if self.selectedStock.status != None:self.stockValues[2].set(self.selectedStock.status)
			if self.selectedStock.deliveryQuantity != None:self.stockValues[6].set(self.selectedStock.deliveryQuantity)
			if self.selectedStock.stockQuantity != None:self.stockValues[7].set(self.selectedStock.stockQuantity)
			if self.selectedStock.alertQuantity != None:self.stockValues[8].set(self.selectedStock.alertQuantity)
			if self.selectedStock.notes != None:self.stockValues[10].set(self.selectedStock.notes)
			# Affichage du Status dans la ComboBox
			status = ((u"ER", 0),(u"EC", 1),(u"LV", 2),(u"OK", 3),(u"AL", 4),(u"LI", 5),(u"SZ", 6),)
			for n in status:
				if n[0] == self.selectedStock.status: self.stockStatusCB.selectitem(n[1])
			if self.selectedStock.deliveryDate != None:
				# Affichage de la date de Livraison
				self.stockValues[4].set(self.selectedStock.deliveryDate.strftime("%d/%m/%Y"))
				# Affichage de l'heure dans la ComboBox 
				count = 0
				for h in self.hoursListCB:
					if h == self.selectedStock.deliveryDate.strftime("%H"): self.hourStockDeliveryDateCB.selectitem(count)
					count+=1
				# Affichage des minutes dans la ComboBox
				count = 0
				for m in self.minutesListCB:
					if m == self.selectedStock.deliveryDate.strftime("%M"): self.minStockDeliveryDateCB.selectitem(count)
					count+=1
				# Mise à jour des variables heure et minutes
				self.stockHourDeliveryDate.set(self.selectedStock.deliveryDate.strftime("%H"))
				self.stockMinuteDeliveryDate.set(self.selectedStock.deliveryDate.strftime("%M"))
			# activation du bouton supprimer
			self.deleteStockBt.config(state=NORMAL)

	def searchStock(self, event=None):
		if self.searchStockValue.get() != "":
			self.listStock.delete(0,END)
			self.idListStock = []
			result = Stock.select(Stock.q.notes.startswith(self.searchStockValue.get().encode("utf-8")), orderBy=Stock.q.item)
			for row in result:
				self.listStock.insert(END, row.item.designation+" - "+row.place.company+" - "+row.status+" - "+row.stockQuantity)
				self.idListStock.append(row.id)
		else:
			self.listStock.delete(0,END)
			self.idListStock = []
			result = Stock.select(orderBy=Stock.q.item)
			for row in result:
				self.listStock.insert(END, row.item.designation+" - "+row.place.company+" - "+row.status+" - "+str(row.stockQuantity))
				self.idListStock.append(row.id)

	def makeStock(self):
		leftFrame = Frame(self)
		# Fiche Stock  (présentation colonne de gauche)
		Label(leftFrame, text=u"Stock").pack(side=TOP, fill=X)
		# Création des champs a renseigner pour un object Stock
		stockStatusListCB =  (u"En Rupture", u"En Commande", u"Livré", u"Ok", u"En Alerte", u"En Litige", u"Stock Zéro")
		stockLabels = (u"Résidence", u"Article", u"Etat",u"Pièce de vente", u"Livré (date)", u"Livré (heure)", u"Quantité livré", u"Quantité en stock", u"Quantité alerte", u"Vérifié par", u"Notes")
		self.stockValues = [StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar()]
		count = 0
		for name in stockLabels:
			f = Frame(leftFrame)
			Label(f, width=18, text=name, anchor=W).pack(side=LEFT)
			if count == 0: # Place
				Entry(f, textvariable=self.stockValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myPlace=Button(f, image=self.imgSearch, command=lambda x=self.stockValues[count]:self.ctrlListPlace(x), padx=4, pady=1)
				myPlace.pack(side=RIGHT)
				self.balloon.bind(myPlace, u"Séléctionner une Résidence")
			elif count == 1: # Item
				Entry(f, textvariable=self.stockValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myItem=Button(f, image=self.imgSearch, command=lambda x=self.stockValues[count]:self.ctrlListItem(x), padx=4, pady=1)
				myItem.pack(side=RIGHT)
				self.balloon.bind(myItem, u"Séléctionner un Article")
			elif count == 2: # Status
				self.stockStatusCB=Pmw.ComboBox(f, selectioncommand=self.stockStatus, scrolledlist_items=stockStatusListCB, listheight=140)
				self.stockStatusCB._entryfield._entryFieldEntry.config( width=21)
				self.stockStatusCB.pack(side=LEFT, fill=X)
				self.stockStatusCB.selectitem(1)
				self.stockValues[count].set(u"EC")
			elif count == 3: # Bill
				Entry(f, textvariable=self.stockValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myBill=Button(f, image=self.imgSearch, command=lambda x=self.stockValues[count]:self.ctrlListBill(x), padx=4, pady=1)
				myBill.pack(side=RIGHT)
				self.balloon.bind(myBill, u"Séléctionner une Pièce de vente")
			elif count == 4: # Livré date
				Entry(f, textvariable=self.stockValues[count], width=21).pack(side=LEFT, fill=X)
				myCal1=Button(f, image=self.imgCalendar, command=lambda x=self.stockValues[count]:self.ctrlCalendar(x), padx=4, pady=1)
				myCal1.pack(side=LEFT)
				self.balloon.bind(myCal1, u"Calendrier")
			elif count == 5: # Livré heure
				hStartLb1=Label(f, width=2, text="H", anchor=W)
				hStartLb1.pack(side=LEFT)
				self.balloon.bind(hStartLb1, u"Heure")
				self.hourStockDeliveryDateCB=Pmw.ComboBox(f, selectioncommand=self.stockHourDeliveryDate, scrolledlist_items=self.hoursListCB, listheight=100)
				self.hourStockDeliveryDateCB._entryfield._entryFieldEntry.config( width = 3)
				self.hourStockDeliveryDateCB.pack(side=LEFT)
				mStartLb1=Label(f, width=3, text="mn", anchor=W)
				mStartLb1.pack(side=LEFT)
				self.balloon.bind(mStartLb1, u"minutes")
				self.minStockDeliveryDateCB=Pmw.ComboBox(f, selectioncommand=self.stockMinuteDeliveryDate, scrolledlist_items=self.minutesListCB, listheight=100)
				self.minStockDeliveryDateCB._entryfield._entryFieldEntry.config( width = 3)
				self.minStockDeliveryDateCB.pack(side=LEFT)
				# Menu Time
				myTime1=Button(f, image=self.imgTime, padx=1, pady=1)
				myTime1.pack(side=RIGHT)
				myTime1.bind("<ButtonRelease-1>",self.ctrlTimeNow1)
				self.balloon.bind(myTime1, u"Séléctionner une heure")
			elif count == 9: # Staff
				Entry(f, textvariable=self.stockValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myStaff=Button(f, image=self.imgSearch, command=lambda x=self.stockValues[count]:self.ctrlListStaff(x), padx=4, pady=1)
				myStaff.pack(side=RIGHT)
				self.balloon.bind(myStaff, u"Séléctionner un Employé")
			elif count == 10: # Notes
				Entry(f, textvariable=self.stockValues[count], width=21).pack(side=LEFT, fill=X)
				myNotes=Button(f, image=self.imgNotes, command=lambda x=self.stockValues[count]:self.ctrlNotes(x,u"Notes stock"), padx=4, pady=1)
				myNotes.pack(side=RIGHT)
				self.balloon.bind(myNotes, u"Détails de la note")
			else: 
				Entry(f, textvariable=self.stockValues[count], width=24).pack(side=LEFT, fill=X)
			f.pack(side=TOP, fill=X)
			count += 1
		# Boutons enregistrement (new ou modify) et suppression
		s = Frame(leftFrame) 
		self.saveStockBt=Button(s, image=self.imgSave, command=self.createStock)
		self.saveStockBt.bind("<Return>", self.createStock)
		self.saveStockBt.pack(side=LEFT)
		self.balloon.bind(self.saveStockBt, u"Enregistrer")
		self.deleteStockBt=Button(s, image=self.imgDelete, command=self.deleteStock, state=DISABLED)
		self.deleteStockBt.bind("<Return>", self.deleteStock)
		self.deleteStockBt.pack(side=LEFT)
		self.balloon.bind(self.deleteStockBt, u"Supprimer")
		s.pack(side=TOP, fill=X)
		leftFrame.pack(side=LEFT, fill=X)
		# Liste des Stock existants (présentation colonne de droite)
		rightFrame = Frame(self) 
		Label(rightFrame, text=u"Liste des Stocks").pack(side=TOP, fill=X)
		self.searchStockValue = StringVar()
		self.searchStockEt = Entry(rightFrame,  width=53, textvariable=self.searchStockValue, relief=GROOVE)
		self.searchStockEt.bind("<KeyRelease>", self.searchStock)
		self.searchStockEt.pack(side=TOP, fill=X)
		self.balloon.bind(self.searchStockEt, u"Saisir les premières lettres d'une Stock\npour une recherche plus précise,\nla liste est classée par désignation.")
		s = Frame(rightFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listStock = Listbox(s)
		self.listStock.config(yscrollcommand=scrollbar.set, width=50, selectmode=SINGLE, height=15)
		self.listStock.bind("<ButtonRelease-1>",self.selectStock)
		scrollbar.config(command=self.listStock.yview)
		self.listStock.pack()
		self.balloon.bind(self.listStock, u"Séléctionner une Stock\npour la visualiser ou la modifier.")
		s.pack(side=TOP, fill=X)
		rightFrame.pack(side=RIGHT, fill=BOTH)
		# Initialisation
		self.clearFieldStock()
		self.searchStock()

	def ctrlTimeNow1(self,event):
		varHour=[self.stockHourDeliveryDate, self.stockMinuteDeliveryDate, self.hourStockDeliveryDateCB, self.minStockDeliveryDateCB] 
		TimePopupGUI(self, event=event, field=self.stockValues[5], varHour=varHour, log=self.log, path=self.path)

	def ctrlCalendar(self,field):
		CalendarGUI(field=field, log=self.log, path=self.path)

	def ctrlNotes(self,field,title):
		NotesGUI(field=field,title=title, log=self.log, path=self.path)

	def ctrlListPlace(self,field): # index 0
		PlaceListGUI(balloon=self.balloon, field=field, index=0, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlListItem(self,field): # index 1
		ItemListGUI(balloon=self.balloon, field=field, index=1, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlListBill(self,field): # index 2
		BillListGUI(balloon=self.balloon, field=field, index=2, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlListStaff(self,field): # index 3
		StaffListGUI(balloon=self.balloon, field=field, index=3, listObject=self.listObject, log=self.log, path=self.path)

	def stockStatus(self, value):
		status =  ((u"ER", u"En Rupture"),(u"EC", u"En Commande"),(u"LV", u"Livré"),(u"OK", u"Ok"),(u"AL", u"En Alerte"),(u"LI", u"En Litige"),(u"SZ", u"Stock Zéro"),)
		for n in status:
			if n[1] == value: self.stockValues[2].set(n[0])

	def stockHourDeliveryDate(self, value):
		self.stockHourDeliveryDate.set(value)
		self.minStockDeliveryDateCB.selectitem(0)
		self.minStockDeliveryDateCB.invoke()

	def stockMinuteDeliveryDate(self, value):
		self.stockMinuteDeliveryDate.set(value)

	def getDateTimeDeliveryDateStock(self):
		if self.stockValues[4].get() != "":
			date=self.stockValues[4].get().split("/")
			d = datetime.datetime(int(date[2]), int(date[1]), int(date[0]), int(self.stockHourDeliveryDate.get()), int(self.stockMinuteDeliveryDate.get()), 0)
			return d
		else:
			return None

	def verifyStock(self):
		if self.stockValues[0].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Résidence est obligatoire !\nMerci de le compléter.")
			return False
		elif self.stockValues[1].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Article est obligatoire !\nMerci de le compléter.")
			return False
		elif self.stockValues[4].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Date de livraison est obligatoire !\nMerci de le compléter.")
			return False
		elif self.stockValues[6].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Quantité livrée est obligatoire !\nMerci de le compléter.")
			return False            
		elif self.stockValues[9].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Vérifié par est obligatoire !\nMerci de le compléter.")
			return False
		elif self.stockHourDeliveryDate.get() == "" or  self.stockMinuteDeliveryDate.get() == "": 
			showerror(u"Erreur de saisie", u"Les champs Heures et Minutes de la Livraison sont obligatoire !\nMerci de les compléter.")
			return False
		else:
			return True

	def createStock(self, event=None):
		if self.verifyStock():
			if  self.deleteStockBt.config()["state"][4] == "normal":
				self.modifyStock()
			else:
				if askyesno(u"Enregistrement", u"Souhaitez-vous enregistrer %s comme une nouvelle Stock ?\n" % self.stockValues[1].get()):
					Stock(place=self.listObject[0],
						item=self.listObject[1],
						status=self.stockValues[2].get().encode("utf-8"),
						bill=self.listObject[2],
						deliveryDate=self.getDateTimeDeliveryDateStock(),
						deliveryQuantity=self.stockValues[6].get().encode("utf-8"),
						stockQuantity=self.stockValues[7].get().encode("utf-8"),
						alertQuantity=self.stockValues[8].get().encode("utf-8"),
						checkBy=self.listObject[3],
						notes=self.stockValues[10].get().encode("utf-8"),
						createDate=datetime.datetime.now()
					)
					self.searchStock()
				self.clearFieldStock()

	def modifyStock(self, event=None):
		if askyesno(u"Modifier", u"Souhaitez-vous modifier la Stock %s ?" % self.selectedStock.id):
			self.selectedStock.place=self.listObject[0]
			self.selectedStock.item=self.listObject[1]
			self.selectedStock.status=self.stockValues[2].get().encode("utf-8")
			self.selectedStock.bill=self.listObject[2]
			self.selectedStock.deliveryDate=self.getDateTimeDeliveryDateStock()
			self.selectedStock.deliveryQuantity=self.stockValues[6].get().encode("utf-8")
			self.selectedStock.stockQuantity=self.stockValues[7].get().encode("utf-8")
			self.selectedStock.alertQuantity=self.stockValues[8].get().encode("utf-8")
			self.selectedStock.checkBy=self.listObject[3]
			self.selectedStock.notes=self.stockValues[10].get().encode("utf-8")
			self.searchStock()
		self.deleteStockBt.config(state=DISABLED)
		self.clearFieldStock()

	def deleteStock(self, event=None):
		if askyesno(u"Suppression", u"Souhaitez-vous supprimer la Stock %s ?\nCette opération est irréversible !" % self.selectedStock.id):
			Stock.delete(self.selectedStock.id)
			self.searchStock()
		self.deleteStockBt.config(state=DISABLED)
		self.clearFieldStock()
	# FIN de la gestion du module Stock ------------------------------------------------------------------------------------------------------------------------

class StockListGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, field=None, index=None, listObject=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.title(u"Liste des Stocks")
		self.balloon=balloon
		self.imgNew=PhotoImage(file="img/add_alternative_icon.gif")
		self.field=field
		self.index=index
		self.listObject=listObject
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Stock-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Stock-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre...")
		self.log.info("\tStockListGUI\tStart")
		self.makeListStock()

	def selectListStock(self, event):
		if self.listListStock.get(0)!="":
			result = Stock.select(Stock.q.id==self.idListListStock[int(self.listListStock.curselection()[0])])
			for row in result:
				self.listObject[self.index]=row
				self.field.set(row.item.designation)
				self.destroy()

	def searchListStock(self, event=None):
		if self.searchListStockValue.get() != "":
			self.listListStock.delete(0,END)
			self.idListListStock = []
			result = Stock.select(Stock.q.notes.startswith(self.searchListStockValue.get().encode("utf-8")), orderBy=Stock.q.item)
			for row in result:
				self.listListStock.insert(END, row.item.designation+" - "+row.place.company+" - "+row.status+" - "+str(row.stockQuantity))
				self.idListListStock.append(row.id)
		else:
			self.listListStock.delete(0,END)
			self.idListListStock = []
			result = Stock.select(orderBy=Stock.q.item)
			for row in result:
				self.listListStock.insert(END, row.item.designation+" - "+row.place.company+" - "+row.status+" - "+str(row.stockQuantity))
				self.idListListStock.append(row.id)

	def makeListStock(self):
		leftFrame = Frame(self)
		Label(leftFrame, text=u"Liste des Stockes").pack(side=TOP, fill=X)
		self.searchListStockValue = StringVar()
		s = Frame(leftFrame) 
		self.searchListStockEt = Entry(s,  width=42, textvariable=self.searchListStockValue, relief=GROOVE)
		self.searchListStockEt.bind("<KeyRelease>", self.searchListStock)
		self.searchListStockEt.pack(side=LEFT, fill=X)
		self.balloon.bind(self.searchListStockEt, u"Saisir les premiéres lettres de la designation d'une Stocke d'un Séjour\npour une recherche plus précise,\nla liste est classée par Désignation.")
		newStockBt=Button(s, image=self.imgNew, command=self.ctrlStock)
		newStockBt.pack(side=RIGHT)
		self.balloon.bind(newStockBt, u"Créer une nouveau Stock")
		s.pack(side=TOP, fill=X)
		s = Frame(leftFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listListStock = Listbox(s)
		self.listListStock.config(yscrollcommand=scrollbar.set,width=43, selectmode=SINGLE, height=16)
		self.listListStock.bind("<ButtonRelease-1>",self.selectListStock)
		scrollbar.config(command=self.listListStock.yview)
		self.listListStock.pack()
		self.balloon.bind(self.listListStock, u"Séléctionner un Séjour.")
		s.pack(side=TOP, fill=X)
		leftFrame.pack()
		self.searchListStock()

	def ctrlStock(self):
		StockGUI(balloon=self.balloon, log=self.log, path=self.path)